#include "system_stm32c8t6.h"

#define VECT_TAB_OFFSET  0x00000000U

uint32_t SystemCoreClock = 8000000;
const uint8_t AHBPrescTable[16U] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
const uint8_t APBPrescTable[8U] =  {0, 0, 0, 0, 1, 2, 3, 4};


void SystemInit (void)
{
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCC->CR |= 0x00000001U;
  RCC->CFGR &= 0xF8FF0000U;

  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= 0xFEF6FFFFU;

  /* Reset HSEBYP bit */
  RCC->CR &= 0xFFFBFFFFU;

  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC->CFGR &= 0xFF80FFFFU;

  RCC->CIR = 0x009F0000U;

  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
}

void SystemCoreClockUpdate (void)
{
  uint32_t tmp = 0U, pllmull = 0U, pllsource = 0U;

  /* Get SYSCLK source -------------------------------------------------------*/
  tmp = RCC->CFGR & RCC_CFGR_SWS;
  
  switch (tmp)
  {
    case 0x00U:  /* HSI used as system clock */
      SystemCoreClock = HSI_VALUE;
      break;
    case 0x04U:  /* HSE used as system clock */
      SystemCoreClock = HSE_VALUE;
      break;
    case 0x08U:  /* PLL used as system clock */

      /* Get PLL clock source and multiplication factor ----------------------*/
      pllmull = RCC->CFGR & RCC_CFGR_PLLMULL;
      pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
      pllmull = ( pllmull >> 18U) + 2U;
      
      if (pllsource == 0x00U)
      {
        /* HSI oscillator clock divided by 2 selected as PLL clock entry */
        SystemCoreClock = (HSI_VALUE >> 1U) * pllmull;
      }
      else
      {
        /* HSE selected as PLL clock entry */
        if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET)
        {/* HSE oscillator clock divided by 2 */
          SystemCoreClock = (HSE_VALUE >> 1U) * pllmull;
        }
        else
        {
          SystemCoreClock = HSE_VALUE * pllmull;
        }
      }
      break;

    default:
      SystemCoreClock = HSI_VALUE;
      break;
  }
  
  /* Compute HCLK clock frequency ----------------*/
  /* Get HCLK prescaler */
  tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)];
  /* HCLK clock frequency */
  SystemCoreClock >>= tmp;  
}

/**
 * 选择 PLL 作为系统时钟源，启用 HSE
 */
void SystemClock_Config(void) {
  // 1. 启用 HSE
  RCC->CR |= RCC_CR_HSEON;  // 使能 HSE
  while (!(RCC->CR & RCC_CR_HSERDY));  // 等待 HSE 稳定

  // 2. 配置 PLL
  // - HSE 作为 PLL 输入
  // - PLL 倍频系数为 9（8 MHz * 9 = 72 MHz）
  RCC->CFGR &= ~RCC_CFGR_PLLSRC;  // 清除 PLL 源选择位
  RCC->CFGR |= RCC_CFGR_PLLSRC_HSE;  // 选择 HSE 作为 PLL 输入
  RCC->CFGR &= ~RCC_CFGR_PLLMULL;  // 清除 PLL 倍频系数位
  RCC->CFGR |= RCC_CFGR_PLLMULL9;  // 设置 PLL 倍频系数为 9

  // 3. 启用 PLL
  RCC->CR |= RCC_CR_PLLON;  // 使能 PLL
  while (!(RCC->CR & RCC_CR_PLLRDY));  // 等待 PLL 稳定

  // 4. 配置 Flash 预取指和等待状态
  FLASH->ACR |= FLASH_ACR_PRFTBE;  // 使能 Flash 预取指
  FLASH->ACR &= ~FLASH_ACR_LATENCY;  // 清除等待状态位
  FLASH->ACR |= FLASH_ACR_LATENCY_2;  // 设置等待状态为 2（适用于 48 MHz < SYSCLK ≤ 72 MHz）

  // 5. 选择 PLL 作为系统时钟源
  RCC->CFGR &= ~RCC_CFGR_SW;  // 清除系统时钟源选择位
  RCC->CFGR |= RCC_CFGR_SW_PLL;  // 选择 PLL 作为系统时钟源
  while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);  // 等待时钟源切换完成

  // 6. 更新 SystemCoreClock 变量
  SystemCoreClock = 72000000;  // 72 MHz
}
